package casts.misc
{
   import flash.display.Bitmap;
   import flash.display.BitmapData;
   import flash.display.Loader;
   import flash.display.MovieClip;
   import flash.display.Sprite;
   import flash.events.Event;
   import flash.events.IOErrorEvent;
   import flash.events.MouseEvent;
   import flash.net.URLRequest;
   // greensock
   import com.greensock.TweenMax;

   /**
    * 圖片容器，照片會被設定在 FIX_WIDTH x FIX_HEIGHT 尺寸裡，mouse over後圖會回復到原本size，而且隨滑鼠位置做移動；mouse out則是回復原size和位置。
    * @author     cjboy | cjboy1984@gmail.com
    * @usage
    * loadImg('img/normal.jpg');
    */
   public class PhotoContainer_2 extends MovieClip
   {
      // 圖片顯示的範圍
      public static const FIX_WIDTH:Number = 602;
      public static const FIX_HEIGHT:Number = 412;

      // loader
      private var msk:Sprite = new Sprite();
      private var bmpLoader:Loader;
      private var bmp:Bitmap;

      // bmp
      private var scaleXY:Number; // 照片剛好fit框架的縮放比
      private var fitX:Number; // 照片fit後的x
      private var fitY:Number; // 照片fit後的y
      private var offX:Number; // 照片原寬減掉框的寬
      private var offY:Number; // 照片原高減掉框的高

      // 是否鎖住 mouse over 效果
      public static var lock:Boolean = false;

      /* constructor */
      public function PhotoContainer_2()
      {
         stop();

         addEventListener(Event.ADDED_TO_STAGE, onAdd);
         addEventListener(Event.REMOVED_FROM_STAGE, onRemove);
      }

      // --------------------- LINE ---------------------

      public function loadImg(img:String):void
      {
         if (!img) return;

         // 先清掉舊資料
         if (bmpLoader)
         {
            bmpLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
            bmpLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onBmpLoaded);
            bmpLoader.unloadAndStop();
            bmpLoader = null;
         }

         bmpLoader = new Loader();
         bmpLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOErr);
         bmpLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBmpLoaded);
         bmpLoader.load(new URLRequest(img));
      }

      // ################### protected ##################

      // #################### private ###################

      private function onAdd(e:Event):void
      {
         alpha = 0;
         lock = false;

         // mouse
         addEventListener(MouseEvent.ROLL_OVER, onOver);
         addEventListener(MouseEvent.ROLL_OUT, onOut);
      }

      private function onRemove(e:Event):void
      {
         TweenMax.killTweensOf(this);

         // mouse
         removeEventListener(MouseEvent.ROLL_OVER, onOver);
         removeEventListener(MouseEvent.ROLL_OUT, onOut);
         removeEventListener(MouseEvent.MOUSE_MOVE, zoomIn);

         if (contains(msk)) removeChild(msk);

         if (bmp)
         {
            TweenMax.killTweensOf(bmp);
            removeChild(bmp);
         }

         if (bmpLoader)
         {
            bmpLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
            bmpLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onBmpLoaded);
            bmpLoader.unload();
            bmpLoader = null;
         }
      }

      // --------------------- LINE ---------------------

      private function onOver(e:MouseEvent):void
      {
         if (mouseX >= 0 && mouseX <= FIX_WIDTH &&
             mouseY >= 0 && mouseY <= FIX_HEIGHT &&
             alpha > 0 && scaleXY < 1)
         {
            zoomIn();
            addEventListener(MouseEvent.MOUSE_MOVE, zoomIn);
         }
      }

      private function onOut(e:MouseEvent):void
      {
         removeEventListener(MouseEvent.MOUSE_MOVE, zoomIn);
         zoomOut();
      }

      private function zoomIn(e:MouseEvent = null):void
      {
         if (lock)
         {
            zoomOut();
            return;
         }

         var adjust:Number = 60;
         var sensor_width:Number = FIX_WIDTH - 2 * adjust;
         var sensor_height:Number = FIX_HEIGHT - 2 * adjust;

         var perc_x:Number;
         var perc_y:Number;
         // x
         if (mouseX <= adjust)
         {
            perc_x = 0;
         }
         else if (mouseX >= FIX_WIDTH - adjust)
         {
            perc_x = 1;
         }
         else
         {
            perc_x = (mouseX - adjust) / sensor_width;
         }
         // y
         if (mouseY <= adjust)
         {
            perc_y = 0;
         }
         else if (mouseY >= FIX_HEIGHT - adjust)
         {
            perc_y = 1;
         }
         else
         {
            perc_y = (mouseY - adjust) / sensor_height;
         }

         // 修正
         //if (perc_x > 1) perc_x = 1;
         //if (perc_y > 1) perc_y = 1;

         // 處理縮放
         TweenMax.to(bmp, 0.3, { scaleX:1, scaleY:1 } );
         // 處理x
         if(offX > 0) TweenMax.to(bmp, 0.3, { x:-perc_x * offX } );
         // 處理y
         if(offY > 0) TweenMax.to(bmp, 0.3, { y:-perc_y * offY } );
      }

      private function zoomOut():void
      {
         TweenMax.to(bmp, 0.3, { x:fitX, y:fitY, scaleX:scaleXY, scaleY:scaleXY } );
      }

      // --------------------- LINE ---------------------

      private function onBmpLoaded(e:Event):void
      {
         bmpLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
         bmpLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onBmpLoaded);

         bmp = Bitmap(bmpLoader.content);
         bmp.smoothing = true;
         // save info
         offX = bmp.width - FIX_WIDTH;
         offY = bmp.height - FIX_HEIGHT;
         MyUtils.scaleToFillArea(bmp, FIX_WIDTH, FIX_HEIGHT, 'proportionalOutside');
         bmp.x = (FIX_WIDTH - bmp.width) / 2;
         bmp.y = (FIX_HEIGHT - bmp.height) / 2;
         bmp.mask = msk;
         addChild(bmp);

         // save info
         scaleXY = bmp.scaleX;
         fitX = bmp.x;
         fitY = bmp.y;

         // create mask
         msk.graphics.clear();
         msk.graphics.beginFill(0x0000ff);
         msk.graphics.drawRect(0, 0, FIX_WIDTH, FIX_HEIGHT);
         msk.graphics.endFill();
         addChild(msk);

         TweenMax.to(this, 0.5, { alpha:1 } );
      }

      private function onIOErr(e:IOErrorEvent):void
      {
         bmpLoader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIOErr);
         bmpLoader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onBmpLoaded);
      }

      // --------------------- LINE ---------------------

   }

}